from quant.markets import Channel, Handler
from quant.accounts.api import Api, Spi
from quant.const import Exchange
from quant.exchanges._factory import add_factory
from quant.exchanges.basics import ApiRouter, SpiRouter, FunctionsRouter
from quant.exchanges.util import get_agent_name
from quant.exchanges.kucoin_spot import KucoinSpotChannel, KucoinSpotHandler, KucoinSpotApi, KucoinSpotSpi, KucoinSpotFunctions
from quant.exchanges.kucoin_spot import KucoinSpotFunctions
from quant.exchanges.kucoin_swap import KucoinSwapFunctions


class KucoinChannel(Channel):
    agent: Channel

    def init(self):
        agent_name = get_agent_name(self.symbol)
        agent_cls = _channel_agent_map[agent_name]
        self.agent = agent_cls(self.event, self.exchange, self.symbol, self.frequency, self.markets)

    def connect(self):
        return self.agent.connect()

    def disconnect(self):
        return self.agent.disconnect()

    def is_open(self):
        return self.agent.is_open()


class KucoinHandler(Handler):
    agent: Handler

    def init(self):
        agent_name = get_agent_name(self.symbol)
        agent_cls = _handler_agent_map[agent_name]
        self.agent = agent_cls(self.event, self.exchange, self.symbol, self.frequency, self.markets)

    def process(self, routing_key, recv_time, raw):
        return self.agent.process(routing_key, recv_time, raw)


class KucoinApi(ApiRouter):
    def _create_agent(self):
        params = (self.keys, self.account)
        self.agent_map = {n: cls(*params) for n, cls in _api_agent_map.items()}

    def _get_agent(self, symbol):
        agent_name = get_agent_name(symbol)
        try:
            agent: Api = self.agent_map[agent_name]
        except KeyError:
            err = 'Agent for {} not implemented!'.format(symbol)
            raise NotImplementedError(err)
        return agent


class KucoinSpi(SpiRouter):
    def _create_agent(self):
        params = (self.keys, self.account)
        self.agent_map = {n: cls(*params) for n, cls in _spi_agent_map.items()}

    def _get_agent(self, symbol):
        agent_name = get_agent_name(symbol)
        try:
            agent: Spi = self.agent_map[agent_name]
        except KeyError:
            err = 'Agent for {} not implemented!'.format(symbol)
            raise NotImplementedError(err)
        return agent


class KucoinFunctions(FunctionsRouter):
    def _create_agent(self):
        self.agent_map = {n: cls() for n, cls in _exchange_function_map.items()}

    def _get_agent(self, symbol):
        agent_name = get_agent_name(symbol)
        return self.agent_map[agent_name]


from quant.exchanges.util import NullCls
# _channel_agent_map = {'spot': KucoinSpotChannel, 'usdt.swap': KucoinSwapUsdtChannel}
# _handler_agent_map = {'spot': KucoinSpotHandler, 'usdt.swap': KucoinSwapUsdtHandler}
# _api_agent_map = {'spot': KucoinSpotApi, 'usdt.swap': KucoinSwapUsdtApi}
# _spi_agent_map = {'spot': KucoinSpotSpi, 'usdt.swap': KucoinSwapUsdtSpi}
# _exchange_function_map = {'spot': KucoinSpotFunctions, 'usdt.swap': NullCls}

_channel_agent_map = {'spot': KucoinSpotChannel, 'usdt.swap': NullCls}
_handler_agent_map = {'spot': KucoinSpotHandler, 'usdt.swap': NullCls}
_api_agent_map = {'spot': NullCls, 'usdt.swap': NullCls}
_spi_agent_map = {'spot': NullCls, 'usdt.swap': NullCls}
_exchange_function_map = {'spot': KucoinSpotFunctions, 'usdt.swap': KucoinSwapFunctions}

add_factory(Exchange.Kucoin, KucoinChannel, KucoinHandler, KucoinApi, KucoinSpi, KucoinFunctions)
